# coding=utf-8
# author=haishan09@gmail.com
import json
from django.forms import widgets
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.encoding import force_text


class JsonifyConfigWidget(widgets.MultiWidget):

    def __init__(self, config, attrs=None):
        self.config = config
        self.attrs = attrs
        super(JsonifyConfigWidget, self).__init__(self.widgets_from_config, attrs)

    @property
    def widgets_from_config(self):
        return [self.get_widget(property) for property in self.config.config]

    def get_widget(self, property):
        attrs = self.attrs or {}
        widget_name = property.get('widget')
        if widget_name == 'TextInput':
            widget = widgets.TextInput(attrs=attrs)
        elif widget_name == 'Textarea':
            widget = widgets.Textarea(attrs=attrs.update({'rows': int(property.get('rows', 5))}) or attrs)
        elif widget_name == 'Select':
            widget = widgets.Select(choices=property.get('choices'), attrs=attrs)
        elif widget_name == 'NumberInput':
            widget = widgets.NumberInput(attrs=attrs)
        elif widget_name == 'Checkbox':
            widget = widgets.CheckboxInput()
        elif widget_name == 'JsonifyConfigWidget':
            widget = JsonifyConfigWidget(property.get('config'), attrs=attrs)
        elif widget_name == 'JsonifyListConfigWidget':
            pk = property.get('pk')
            widget = JsonifyListConfigWidget(property.get('configs'), pk=pk, attrs=attrs)
        return widget
        
    def decompress(self, value):
        value_type = type(value)
        if value_type == unicode:
            value = json.loads(value.encode('utf-8'))
        if value_type == str:
            value = json.loads(value)
        if value:
            return [value.get(key) for key in self.config.names]
        return self.config.defaults

    def format_output(self, rendered_widgets):
        rendered_content = ''
        for label, name, rendered_widget in zip(self.config.labels, self.config.names, rendered_widgets):
            rendered_content += '<tr><td class="property-%s-label">%s</td><td class="property-%s">' % (name, label, name) + rendered_widget + '</td></tr></td>'
        return '<table style="box-shadow:none;width:100%" class="property-table">' + rendered_content + '</table>'

    def value_from_datadict(self, data, files, name):
        datalist = [
            widget.value_from_datadict(data, files, name + '_%s' % i) for i, widget in enumerate(self.widgets)]
        return json.dumps(dict(zip(self.config.names, datalist)))


class JsonifyListConfigWidget(widgets.MultiWidget):

    def __init__(self, configs, pk=None, attrs=None):
        self.pk = pk
        self.configs = configs
        _widgets = [JsonifyConfigWidget(c) for c in self.configs]
        super(JsonifyListConfigWidget, self).__init__(_widgets, attrs)
        
    def decompress(self, value):
        ret_value_list = []
        value_list = map(lambda v: json.loads(v), json.loads(value or '[]'))
        for config in self.configs:
            value_list_filter = filter(lambda v: v.get(self.pk) == config.name, value_list)
            if value_list_filter:
                ret_value_list.append(json.dumps(value_list_filter[0]))
            else:
                ret_value_list.append(config.defaults)
        return ret_value_list

    def format_output(self, rendered_widgets):
        rendered_content = ''
        for rendered_widget in rendered_widgets:
            rendered_content += '<div>' + rendered_widget + '</div>'
        return '<div class="property-list">' + rendered_content + '</div>'

    def value_from_datadict(self, data, files, name):
        datalist = [
            widget.value_from_datadict(data, files, name + '_%s' % i) for i, widget in enumerate(self.widgets)]
        return json.dumps(datalist)


class FontawesomeSelect(widgets.Select):

    def __init__(self, *args, **kwargs):
        super(FontawesomeSelect, self).__init__(*args, **kwargs)
        self.attrs.update({'style': "font-family: 'FontAwesome', sans-serif;"})

    def render_option(self, selected_choices, option_value, option_label):
        if option_value is None:
            option_value = ''
        option_value = force_text(option_value)
        if option_value in selected_choices:
            selected_html = mark_safe(' selected="selected"')
            if not self.allow_multiple_selected:
                selected_choices.remove(option_value)
        else:
            selected_html = ''
        return format_html('<option value="{}"{}>{}</option>',
                           option_value,
                           selected_html,
                           mark_safe(option_label))

    class Media:
        css = {'all': ('css/font-awesome.css', 
                       'css/fontawesome-select.css')}


